Implement Repo::write_content_async
authorFelix Krull <f_krull@gmx.de>
Sun, 1 Sep 2019 12:19:51 +0000 (14:19 +0200)
committerColin Walters <walters@verbum.org>
Fri, 6 May 2022 16:53:54 +0000 (12:53 -0400)
rust-bindings/rust/src/checksum.rs
rust-bindings/rust/src/repo.rs

index 9f07c7d7f9c49603a2e65f9315ad388ee8dc68ec..070e07ed8dd1e5e363eaf81be36b10e41abddf60 100644 (file)
@@ -32,6 +32,12 @@ impl FromGlibPtrFull<*mut [u8; 32]> for Checksum {
     }
 }
 
+impl FromGlibPtrFull<*mut u8> for Checksum {
+    unsafe fn from_glib_full(ptr: *mut u8) -> Self {
+        Checksum::new(ptr as *mut [u8; 32])
+    }
+}
+
 impl fmt::Display for Checksum {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{}", self.to_gstring())
index e84aa1989b23e23d762e5c353f5b894bb58483ae..617bc3a2cff462458997fc98b206877108f88028 100644 (file)
@@ -1,16 +1,20 @@
 #[cfg(any(feature = "v2016_4", feature = "dox"))]
 use crate::RepoListRefsExtFlags;
 use crate::{Checksum, ObjectName, ObjectType, Repo};
+#[cfg(feature = "futures")]
+use futures::future;
 use gio;
+use gio_sys;
 use glib;
 use glib::translate::*;
 use glib::Error;
 use glib::IsA;
 use glib_sys;
 use ostree_sys;
+use std::boxed::Box as Box_;
 use std::collections::{HashMap, HashSet};
 use std::path::Path;
-use std::ptr;
+use std::{mem::MaybeUninit, ptr};
 
 unsafe extern "C" fn read_variant_table(
     _key: glib_sys::gpointer,
@@ -168,4 +172,86 @@ impl Repo {
             }
         }
     }
+
+    pub fn write_content_async<
+        P: IsA<gio::InputStream>,
+        Q: IsA<gio::Cancellable>,
+        R: FnOnce(Result<Checksum, Error>) + Send + 'static,
+    >(
+        &self,
+        expected_checksum: Option<&str>,
+        object: &P,
+        length: u64,
+        cancellable: Option<&Q>,
+        callback: R,
+    ) {
+        let user_data: Box<R> = Box::new(callback);
+        unsafe extern "C" fn write_content_async_trampoline<
+            R: FnOnce(Result<Checksum, Error>) + Send + 'static,
+        >(
+            _source_object: *mut gobject_sys::GObject,
+            res: *mut gio_sys::GAsyncResult,
+            user_data: glib_sys::gpointer,
+        ) {
+            let mut error = ptr::null_mut();
+            let mut out_csum = MaybeUninit::uninit();
+            let _ = ostree_sys::ostree_repo_write_content_finish(
+                _source_object as *mut _,
+                res,
+                out_csum.as_mut_ptr(),
+                &mut error,
+            );
+            let out_csum = out_csum.assume_init();
+            let result = if error.is_null() {
+                Ok(Checksum::from_glib_full(out_csum))
+            } else {
+                Err(from_glib_full(error))
+            };
+            let callback: Box<R> = Box::from_raw(user_data as *mut _);
+            callback(result);
+        }
+        let callback = write_content_async_trampoline::<R>;
+        unsafe {
+            ostree_sys::ostree_repo_write_content_async(
+                self.to_glib_none().0,
+                expected_checksum.to_glib_none().0,
+                object.as_ref().to_glib_none().0,
+                length,
+                cancellable.map(|p| p.as_ref()).to_glib_none().0,
+                Some(callback),
+                Box::into_raw(user_data) as *mut _,
+            );
+        }
+    }
+
+    #[cfg(feature = "futures")]
+    pub fn write_content_async_future<P: IsA<gio::InputStream> + Clone + 'static>(
+        &self,
+        expected_checksum: Option<&str>,
+        object: &P,
+        length: u64,
+    ) -> Box_<dyn future::Future<Output = Result<Checksum, Error>> + std::marker::Unpin> {
+        use fragile::Fragile;
+        use gio::GioFuture;
+
+        let expected_checksum = expected_checksum.map(ToOwned::to_owned);
+        let object = object.clone();
+        GioFuture::new(self, move |obj, send| {
+            let cancellable = gio::Cancellable::new();
+            let send = Fragile::new(send);
+            obj.write_content_async(
+                expected_checksum
+                    .as_ref()
+                    .map(::std::borrow::Borrow::borrow),
+                &object,
+                length,
+                Some(&cancellable),
+                move |res| {
+                    let _ = send.into_inner().send(res);
+                },
+            );
+
+            cancellable
+        })
+    }
 }